<?php

/**
 * Extends the functionality of HMVC library's Module.php class
 *
 * @author Ishtiaque Shahrier <md.ishtiaque@newgenbd.net>
 * @package core
 * @subpackage libraries
 */
class Module_Extended {
    /**
     * Indicates The module is inactive.
     */
    const INACTIVE = 'inactive';
    /**
     * Indicates the module is not installed.
     */
    const NOT_INSTALLED = 'not_installed';
    /**
     * Indicates The module is installed and active.
     */
    const INSTALLED_AND_ACTIVE = 'installed_active';

    /**
     * Checks if a module is loadable.
     *
     * @param string $name
     * @return  constant
     */
    public static function is_loadable($name) {
        include APPPATH . "/config/database.php";

        $aReturn = NULL;
        $link = mysql_connect('localhost', $db[$active_group]['username'], $db[$active_group]['password']);

        if (!$link) {
            return Module_Extended::NOT_INSTALLED;
        } else {
            $selected = mysql_select_db($db[$active_group]['database'], $link);
            if (!$selected)
                return Module_Extended::NOT_INSTALLED;
            $result = mysql_query("SELECT * FROM modules WHERE NAME = '$name' LIMIT 1", $link);
            $aReturn = mysql_num_rows($result) > 0 ? NULL : Module_Extended::NOT_INSTALLED;

            if ($aReturn === NULL) {
                $result = mysql_query("SELECT * FROM modules WHERE NAME = '$name' AND ACTIVE = 1 LIMIT 1", $link);
                $aReturn = mysql_num_rows($result) > 0 ? NULL : Module_Extended::INACTIVE;
            }
            mysql_close($link);
        }

        return $aReturn === NULL ? Module_Extended::INSTALLED_AND_ACTIVE : $aReturn;
    }

    /**
     * Lists all available installed+active modules.
     *
     * @return  array 
     */
    public static function list_active_modules() {
        return Module_Extended::list_modules(TRUE);
    }

    /**
     * Lists all available  modules.
     * @param bool $only_active
     * @return  array
     */
    public static function list_modules($only_active=FALSE) {
        include APPPATH . "/config/database.php";
        static $aReturn = NULL;
        $link = mysql_connect('localhost', $db[$active_group]['username'], $db[$active_group]['password']);

        if (!$link) {
            throw new Exception("Check database configuration.Could not connect.");
        } else {
            $selected = mysql_select_db($db[$active_group]['database'], $link);
            if (!$selected)
                throw new Exception("Check database configuration.Could not select databse [$selected]");
            $result = NULL;
            if ($only_active)
                $result = mysql_query("SELECT * FROM modules ORDER BY load_priority ASC", $link);
            else
                $result = mysql_query("SELECT * FROM modules WHERE ACTIVE=1 ORDER BY load_priority ASC", $link);
            $num = mysql_num_rows($result);
            $i = 0;
            while ($i < $num) {
                $row = mysql_fetch_object($result);
                $aReturn[$row->id] = $row;
                $i++;
            }
            mysql_close($link);
            return $aReturn;
        }
    }

    /**
     * Loads module.And assigns the module into codeigniter's "modules" property.
     * the property "modules" inside $ci is an array fo modules.For each module
     * under the same indeX int the $ci->modules array there would be two elements.
     * one is the basic module information the other one is the module object itself.
     */
    public static function load_modules() {

        $ci = &get_instance();
        if (!isset($ci->db)) {
            throw new Exception("Database Driver is not loaded yet " . __FILE__ . ":" . __LINE__);
        } else {
            if (!isset($ci->modules)) {
                $rows = Module_Extended::list_active_modules();
                foreach ($rows as $module) {
                    $ci->modules[$module->name] = $module;
                    $mod_class_name = "module_u_" . $module->name;
                    $mod = new $mod_class_name($module);
                    $ci->modules[$mod->get_name()]->obj = $mod;
                }
            }
        }
    }

    /**
     * Executes a hook point/function.
     *
     * @param array first elemenet is the interface name and 2nd one is functiona name
     */
    public static function exe_hook($hook_params) {

        $ci = get_instance();
        if (!isset($ci->modules))
            Module_Extended::load_modules();
        $interface = $hook_params[0];
        $function = $hook_params[1];

        foreach ($ci->modules as $module) {
            if (is_a($module->obj, "$interface")) {
                $module->obj->$function();
            }
        }
    }

    /**
     * Returns module object if active and loaded
     * @param string $name
     * @return object|NULL
     */
    public static function get_module_obj($name) {
        $ci = get_instance();
        if (!isset($ci->modules))
            Module_Extended::load_modules();
        if (isset($ci->modules[$name])) {
            return $ci->modules[$name]->obj;
        } else {
            return NULL;
        }
    }

    /**
     * Loads a helper in a specific module
     * @param array|string $helpers nanes of the helpers
     * @param string $moddule  name of the module
     * @return void
     */
    static function load_helper($helpers, $module) {
        $ci = &get_instance();
        if (!is_array($helpers)) {
            $helpers = array($helpers);
        }

        foreach ($helpers as $helper) {
            $helper = strtolower(str_replace(EXT, '', str_replace('_helper', '', $helper)) . '_helper');

            if (isset($ci->_ci_helpers[$helper])) {
                continue;
            }

            $ext_helper = APPPATH . "modules/$module/helpers/" . config_item('subclass_prefix') . $helper . EXT;

            // Is this a helper extension request?
            if (file_exists($ext_helper)) {
                $base_helper = BASEPATH . "helpers/" . $helper . EXT;

                if (!file_exists($base_helper)) {
                    show_error('Unable to load the requested file: helpers/' . $helper . EXT);
                }

                include_once($ext_helper);
                include_once($base_helper);
            } elseif (file_exists(APPPATH . "modules/$module/helpers/" . $helper . EXT)) {
                include_once(APPPATH . "modules/$module/helpers/" . $helper . EXT);
            } else {
                if (file_exists(BASEPATH . 'helpers/' . $helper . EXT)) {
                    include_once(BASEPATH . 'helpers/' . $helper . EXT);
                } else {
                    show_error('Unable to load the requested file: helpers/' . $helper . EXT);
                }
            }

            $ci->_ci_helpers[$helper] = TRUE;
        }
    }

}